package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.OrderStatusEnum;
import com.ruoyi.common.enums.OrderTypeEnum;
import com.ruoyi.common.exception.BusiException;
import com.ruoyi.common.utils.RequestUtil;
import com.ruoyi.common.utils.sign.SignMD5Util;
import com.ruoyi.system.biz.CashBizService;
import com.ruoyi.system.domain.Cash;
import com.ruoyi.system.domain.CashHistory;
import com.ruoyi.system.domain.OrderPay;
import com.ruoyi.system.domain.UserChannel;
import com.ruoyi.system.dto.ApiNotifyDto;
import com.ruoyi.system.dto.ApiOrderPayAddDto;
import com.ruoyi.system.dto.ApiOrderSelectDto;
import com.ruoyi.system.mapper.OrderPayMapper;
import com.ruoyi.system.service.BaseServiceImpl;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.OrderPayService;
import com.ruoyi.system.service.UserChannelService;
import com.ruoyi.system.vo.ApiOrderVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;


@Service
public class OrderPayServiceImpl extends BaseServiceImpl<OrderPayMapper, OrderPay> implements OrderPayService {
    public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);

    @Autowired
    private ISysUserService userService;

    @Resource
    private UserChannelService userChannelService;


    @Resource
    private CashBizService cashService;


    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    @Transactional
    public void createApiOrder(ApiOrderPayAddDto apiOrderReceiveDto) {
        boolean number = NumberUtil.isNumber(apiOrderReceiveDto.getAmount());
        if (!number) {
            throw new BusiException("请传入正确的金额");
        }
        BigDecimal limitAmount = new BigDecimal(1000);
        if (new BigDecimal(1000).compareTo(new BigDecimal(apiOrderReceiveDto.getAmount())) > 0) {
            throw new BusiException("金额不能小于" + limitAmount);
        }
        OrderPay merchantOrder = this.getMerchantOrder(apiOrderReceiveDto.getMerchantId(), apiOrderReceiveDto.getMerchantOrderNo());
        if (merchantOrder != null) {
            throw new BusiException("merchantOrderNo has exist");
        }
        createApiOrder(apiOrderReceiveDto, "");
        threadPoolTaskExecutor.execute(() -> {
            // SmsUtil.sendMsg("18777497575", "999999");
        });
    }


    @Transactional
    public void createApiOrder(ApiOrderPayAddDto apiOrderReceiveDto, String source) {
        Long merchantId = apiOrderReceiveDto.getMerchantId();
        SysUser user = this.userService.checkStatus(merchantId);
        UserChannel userChannel = userChannelService.getOrderPayChannel(merchantId);

        if (!StrUtil.equals("sys", source)) {//下游端需要验签
            SignMD5Util.checkSign(apiOrderReceiveDto, user.getSecertKey());
        }
        OrderPay orderPay = new OrderPay();
        BeanUtil.copyProperties(apiOrderReceiveDto, orderPay);
        String orderNo = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN) + user.getUserId() + (int) (Math.random() * 10) + (int) (Math.random() * 10) + (int) (Math.random() * 10) + (int) (Math.random() * 10);
        orderPay.setOrderNo(orderNo);
        orderPay.setMerchantId(merchantId);
        orderPay.setUsername(user.getUserName());
        orderPay.setReturnStatus(0);
        orderPay.setServiceFee(userChannel.getPayRate().multiply(new BigDecimal(orderPay.getAmount())));
        //获取下单接口返回的url
        //计算手续费
        BigDecimal payRate = userChannel.getPayRate();
        BigDecimal payAmount = userChannel.getPayAmount();
        BigDecimal multiply = new BigDecimal(orderPay.getAmount()).multiply(payRate);
        BigDecimal serviceFee = multiply.add(payAmount);
        orderPay.setServiceFee(serviceFee);
        orderPay.setRemark("单笔:" + payAmount + ";费率:" + payRate.stripTrailingZeros().toString());
        orderPay.setActualAmount(new BigDecimal(orderPay.getAmount()).add(serviceFee));
        Cash cash = cashService.getByUserId(user.getUserId());
        if (cash.getEarning().compareTo(orderPay.getActualAmount()) == -1) {
            throw new BusiException("余额不足");
        }
        //先扣钱 回调失败的时候 给他加回去
        orderPay.setStatus(OrderStatusEnum.handling.getValue());
        this.addDomain(orderPay);
        CashHistory userCashHis = new CashHistory(orderPay.getMerchantId(), orderPay.getActualAmount(), "reduce", "代付订单", "orderPay");
        userCashHis.setOrderNo(orderPay.getOrderNo());
        cashService.updateCash(orderPay.getMerchantId(), userCashHis);
    }


    public OrderPay getMerchantOrder(Long userId, String merchantOrderNo) {
        OrderPay domain = this.getDomain(new OrderPay().setMerchantId(userId).setMerchantOrderNo(merchantOrderNo));

        return domain;
    }

    @Override
    public ApiOrderVo selectApiOrder(ApiOrderSelectDto apiOrderSelectDto) {
        Long merchantId = apiOrderSelectDto.getMerchantId();
        OrderPay orderReceive = this.getMerchantOrder(merchantId, apiOrderSelectDto.getMerchantOrderNo());
//        UserChannel userChannel = userChannelService.checkByUserId(merchantId);
        SysUser sysUser = userService.check(merchantId);
        SignMD5Util.checkSign(apiOrderSelectDto, sysUser.getSecertKey());
        ApiOrderVo apiOrderReceiveVo = BeanUtil.copyProperties(orderReceive, ApiOrderVo.class);
        return apiOrderReceiveVo;

    }

    @Override
    @Transactional
    public void notifyAgent(OrderPay orderReceive) {
        orderReceive.setReceiveStatus(1);
        this.updateDomain(orderReceive);
        if (StrUtil.equals(OrderStatusEnum.reject.getValue(), orderReceive.getStatus())) {
            //如果是 回调状态不是成功的  金额加回去
            CashHistory userCashHis = new CashHistory(orderReceive.getMerchantId(), orderReceive.getActualAmount(), "add", "代付退回", "orderPayReturn");
            userCashHis.setOrderNo(orderReceive.getOrderNo());
            cashService.updateCash(orderReceive.getMerchantId(), userCashHis);
        }

        threadPoolTaskExecutor.execute(() -> {
            //回调下游
            SysUser sysUser = userService.check(orderReceive.getMerchantId());
            ApiNotifyDto apiNotifyDto = BeanUtil.copyProperties(orderReceive, ApiNotifyDto.class);
            apiNotifyDto.setMerchantId(orderReceive.getMerchantId());
            apiNotifyDto.setType(OrderTypeEnum.pay.getValue());
            if (StrUtil.isNotBlank(orderReceive.getPic())) {
                apiNotifyDto.setPic(orderReceive.getPic());
            }
            String serSign = SignMD5Util.getSerSign(apiNotifyDto, sysUser.getSecertKey());
            apiNotifyDto.setSign(serSign);
            int i = 0;
            while (i < 5) {
                String result = RequestUtil.request(orderReceive.getNotifyUrl(), apiNotifyDto, MediaType.APPLICATION_JSON, HttpMethod.POST, null);

                log.info("代付回调下游参数：{},结果:{}", JSONObject.toJSONString(apiNotifyDto), result);
                if (StrUtil.equals("SUCCESS", result) || StrUtil.equals("success", result)) {
                    orderReceive.setReturnStatus(1);
                    this.updateDomain(orderReceive);
                    break;
                }
                try {
                    Thread.sleep(30000L);
                    i++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });
    }

    @Async
    public void notice(OrderPay orderReceive) {
        //回调下游
        SysUser userChannel = userService.check(orderReceive.getMerchantId());
        ApiNotifyDto apiNotifyDto = BeanUtil.copyProperties(orderReceive, ApiNotifyDto.class);
        apiNotifyDto.setMerchantId(orderReceive.getMerchantId());
        apiNotifyDto.setType(OrderTypeEnum.pay.getValue());
        String serSign = SignMD5Util.getSerSign(apiNotifyDto, userChannel.getSecertKey());
        apiNotifyDto.setSign(serSign);
        String result = RequestUtil.request(orderReceive.getNotifyUrl(), apiNotifyDto, MediaType.APPLICATION_JSON, HttpMethod.POST, null);
        log.info("代付回调下游参数：{},结果:{}", JSONObject.toJSONString(apiNotifyDto), result);
        if (StrUtil.equals("SUCCESS", result) || StrUtil.equals("success", result)) {
            orderReceive.setReturnStatus(1);
            this.updateDomain(orderReceive);
            return;
        }


    }

}
